﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Security;
using System.Collections;

namespace DGM.Util.Helpers.Network.Lan
{
  public class LanComputerList
  {
    public static List<string> GetList()
    {
      SV_101_TYPES ServerType = SV_101_TYPES.SV_TYPE_ALL;
      int entriesread = 0, totalentries = 0;
      var alServers = new List<string>();

      do
      {
        // Buffer to store the available servers
        // Filled by the NetServerEnum function
        IntPtr buf = new IntPtr();

        SERVER_INFO_101 server;
        int ret = NetServerEnum(null, 101, out buf, -1,
            ref entriesread, ref totalentries,
            ServerType, null, IntPtr.Zero);

        // if the function returned any data, fill the tree view
        if (ret == ERROR_SUCCESS ||
            ret == ERROR_MORE_DATA ||
            entriesread > 0)
        {
          IntPtr ptr = buf;

          for (int i = 0; i < entriesread; i++)
          {
            // cast pointer to a SERVER_INFO_101 structure
            server = (SERVER_INFO_101)Marshal.PtrToStructure(ptr, typeof(SERVER_INFO_101));

            //Cast the pointer to a ulong so this addition will work on 32-bit or 64-bit systems.
            ptr = (IntPtr)((ulong)ptr + (ulong)Marshal.SizeOf(server));

            // add the machine name and comment to the arrayList. 
            //You could return the entire structure here if desired
            var name = server.sv101_name;

            alServers.Add(name);
          }
        }

        // free the buffer 
        NetApiBufferFree(buf);

      }
      while
          (
          entriesread < totalentries &&
          entriesread != 0
          );

      return alServers;
    }

    public const uint ERROR_SUCCESS = 0;
    public const uint ERROR_MORE_DATA = 234;
    public enum SV_101_TYPES : uint
    {
      SV_TYPE_WORKSTATION = 0x00000001,
      SV_TYPE_SERVER = 0x00000002,
      SV_TYPE_SQLSERVER = 0x00000004,
      SV_TYPE_DOMAIN_CTRL = 0x00000008,
      SV_TYPE_DOMAIN_BAKCTRL = 0x00000010,
      SV_TYPE_TIME_SOURCE = 0x00000020,
      SV_TYPE_AFP = 0x00000040,
      SV_TYPE_NOVELL = 0x00000080,
      SV_TYPE_DOMAIN_MEMBER = 0x00000100,
      SV_TYPE_PRINTQ_SERVER = 0x00000200,
      SV_TYPE_DIALIN_SERVER = 0x00000400,
      SV_TYPE_XENIX_SERVER = 0x00000800,
      SV_TYPE_SERVER_UNIX = 0x00000800,
      SV_TYPE_NT = 0x00001000,
      SV_TYPE_WFW = 0x00002000,
      SV_TYPE_SERVER_MFPN = 0x00004000,
      SV_TYPE_SERVER_NT = 0x00008000,
      SV_TYPE_POTENTIAL_BROWSER = 0x00010000,
      SV_TYPE_BACKUP_BROWSER = 0x00020000,
      SV_TYPE_MASTER_BROWSER = 0x00040000,
      SV_TYPE_DOMAIN_MASTER = 0x00080000,
      SV_TYPE_SERVER_OSF = 0x00100000,
      SV_TYPE_SERVER_VMS = 0x00200000,
      SV_TYPE_WINDOWS = 0x00400000,
      SV_TYPE_DFS = 0x00800000,
      SV_TYPE_CLUSTER_NT = 0x01000000,
      SV_TYPE_TERMINALSERVER = 0x02000000,
      SV_TYPE_CLUSTER_VS_NT = 0x04000000,
      SV_TYPE_DCE = 0x10000000,
      SV_TYPE_ALTERNATE_XPORT = 0x20000000,
      SV_TYPE_LOCAL_LIST_ONLY = 0x40000000,
      SV_TYPE_DOMAIN_ENUM = 0x80000000,
      SV_TYPE_ALL = 0xFFFFFFFF
    };

    [StructLayout(LayoutKind.Sequential)]
    public struct SERVER_INFO_101
    {
      [MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
      public UInt32 sv101_platform_id;
      [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
      public string sv101_name;

      [MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
      public UInt32 sv101_version_major;
      [MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
      public UInt32 sv101_version_minor;
      [MarshalAs(System.Runtime.InteropServices.UnmanagedType.U4)]
      public UInt32 sv101_type;
      [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
      public string sv101_comment;
    };
    public enum PLATFORM_ID
    {
      PLATFORM_ID_DOS = 300,
      PLATFORM_ID_OS2 = 400,
      PLATFORM_ID_NT = 500,
      PLATFORM_ID_OSF = 600,
      PLATFORM_ID_VMS = 700
    }

    #region Dll Imports
    [DllImport("Netapi32", CharSet = CharSet.Unicode)]
    private static extern int NetMessageBufferSend(
        string servername,
        string msgname,
        string fromname,
        string buf,
        int buflen);


    [DllImport("netapi32.dll", EntryPoint = "NetApiBufferFree")]
    public static extern int
        NetApiBufferFree(IntPtr buffer);

    [DllImport("netapi32.dll", EntryPoint = "NetServerEnum")]
    public static extern int NetServerEnum([MarshalAs(UnmanagedType.LPWStr)]string servername,
       int level,
       out IntPtr bufptr,
       int prefmaxlen,
       ref int entriesread,
       ref int totalentries,
       SV_101_TYPES servertype,
       [MarshalAs(UnmanagedType.LPWStr)]string domain,
       IntPtr resume_handle);


    #endregion
  }
}
